﻿using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.ServiceModel.Web;

namespace Restful.Net.TestHost
{
    /// <summary>
    ///  Dummy implementation of a datalogic layer that provides logic and storage for contacts and groups.
    ///  Will not persist objects between restarts.
    ///  Starts with one contact with the ID 123 for the owner bjorn.
    ///  Implemented solely to be able to test the REST interface with a browser.
    /// </summary>
    public class DomainObjectDatabase
    {
        private static readonly Dictionary<string, List<Contact>> Contacts = new Dictionary<string, List<Contact>>();

        static DomainObjectDatabase()
        {
            Contact bjorn = new Contact
                                  {
                                      ContactID = 123,
                                      Name = "Bjørn Bouet Smith",
                                      Emails = new List<string> { "bjornsmith@gmail.com" },
                                      Groups = new List<string> { "friends" }
                                  };
            Contacts.Add("bjorn", new List<Contact> { bjorn });
        }

        public void DeleteContact(string ownerID, long contactID)
        {
            if (!Contacts.ContainsKey(ownerID))
            {
                throw new WebFaultException(HttpStatusCode.NotFound);
            }

            lock (Contacts[ownerID])
            {
                Contact contactInDb = Contacts[ownerID].Find(co => co.ContactID == contactID);
                if (contactInDb == null)
                {
                    throw new WebFaultException(HttpStatusCode.NotFound);
                }
                Contacts[ownerID].Remove(contactInDb);
            }
        }

        public void UpdateContact(string ownerID, long contactID, Contact contact)
        {
            if (!Contacts.ContainsKey(ownerID))
            {
                throw new WebFaultException(HttpStatusCode.NotFound);
            }

            lock (Contacts[ownerID])
            {
                Contact contactInDb = Contacts[ownerID].Find(co => co.ContactID == contactID);
                if (contactInDb == null)
                {
                    CreateContact(ownerID, contact);
                    return;
                }

                Contacts[ownerID].Remove(contactInDb);
                Contacts[ownerID].Add(contact);
            }

        }

        public void CreateContact(string ownerID, Contact contact)
        {
            if (!Contacts.ContainsKey(ownerID))
            {
                lock (Contacts)
                {
                    Contacts.Add(ownerID, new List<Contact>());
                }
            }

            Contacts[ownerID].Add(contact);

        }

        public Contact GetContact(string ownerID, long contactID)
        {
            if (!Contacts.ContainsKey(ownerID))
            {
                throw new WebFaultException(HttpStatusCode.NotFound);
            }

            Contact contact = Contacts[ownerID].Find(co => co.ContactID == contactID);
            if (contact == null)
            {
                throw new WebFaultException<string>(string.Format("Contact with ID:{0} was not found", contactID), HttpStatusCode.NotFound);
            }

            return contact;
        }

        public List<Contact> GetAllContacts(string ownerID)
        {
            if (!Contacts.ContainsKey(ownerID))
            {
                lock (Contacts)
                {
                    Contacts.Add(ownerID, new List<Contact>());
                }
            }

            return Contacts[ownerID];
        }

        public List<Contact> GetAllContacts(string ownerID, string groupName)
        {
            if (!Contacts.ContainsKey(ownerID))
            {
                throw new WebFaultException(HttpStatusCode.NotFound);
            }

            return Contacts[ownerID].Where(co => co.Groups.Contains(groupName)).ToList();
        }
    }

}